﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;
using GingerBeard.Utilities;

namespace GingerBeard.IDL
{
	public enum Language
	{
		CSharp,
		CPlusPlus,
	}

	public enum CodeGeneration
	{
		Off,
		On,
		Optimised
	}

	public class CompileSettings
	{
		Language language;
		public GingerBeard.IDL.Language Language
		{
			get { return language; }
			set { language = value; }
		}
		CodeGeneration codeGenSaving;
		public GingerBeard.IDL.CodeGeneration CodeGenSaving
		{
			get { return codeGenSaving; }
			set { codeGenSaving = value; }
		}
		CodeGeneration codeGenLoading;
		public GingerBeard.IDL.CodeGeneration CodeGenLoading
		{
			get { return codeGenLoading; }
			set { codeGenLoading = value; }
		}
		bool shouldGenerateEndianSwappingCode;
		public bool ShouldGenerateEndianSwappingCode
		{
			get { return shouldGenerateEndianSwappingCode; }
			set { shouldGenerateEndianSwappingCode = value; }
		}
		bool shouldOptimiseFormat;
		public bool ShouldOptimiseFormat
		{
			get { return shouldOptimiseFormat; }
			set { shouldOptimiseFormat = value; }
		}
		TextWriter outputWriter;
		public System.IO.TextWriter OutputWriter
		{
			get { return outputWriter; }
			set { outputWriter = value; }
		}
		int indent = 0;
		public int Indent
		{
			get { return indent; }
			set { indent = value; indentString = ""; for (int i = 0; i < indent; ++i) indentString += "\t"; }
		}
		String indentString = "";
		public String IndentString
		{
			get { return indentString; }
		}
		public void WriteOutputLine(String line)
		{
			OutputWriter.WriteLine(IndentString + line);
		}
	}

	public class Compiler
	{
		private static void ProcessNode_CSharp(IDLNode node, CompileSettings settings)
		{
			if (node.GeneratePre_CSharp(settings))
			{
				foreach (Node cn in node.Nodes)
				{
					settings.Indent++;
					ProcessNode_CSharp(cn as IDLNode, settings);
					settings.Indent--;
				}
			}

			node.GeneratePost_CSharp(settings);
		}

		private static void ProcessNode_CPlusPlus(IDLNode node, CompileSettings settings)
		{
			if (node.GeneratePre_CPlusPlus(settings))
			{
				foreach (Node cn in node.Nodes)
				{
					settings.Indent++;
					ProcessNode_CPlusPlus(cn as IDLNode, settings);
					settings.Indent--;
				}
			}

			node.GeneratePost_CPlusPlus(settings);
		}

		public static void Compile(IDL idl, CompileSettings settings)
		{
			switch (settings.Language)
			{
				case Language.CSharp:
					{
						ProcessNode_CSharp(idl, settings);
						break;
					}
				case Language.CPlusPlus:
					{
						ProcessNode_CPlusPlus(idl, settings);
						break;
					}
			}
		}
	}
}
